<template>
  <Menu
    :selectedKeys="selectedKeys"
    :defaultSelectedKeys="defaultSelectedKeys"
    :mode="mode"
    :openKeys="getOpenKeys"
    :inlineIndent="inlineIndent"
    :theme="theme"
    @openChange="handleOpenChange"
    :class="getMenuClass"
    @click="handleMenuClick"
    :subMenuOpenDelay="0.2"
    v-bind="getInlineCollapseOptions"
  >
    <template v-for="item in items" :key="item.path">
      <BasicSubMenuItem
        :item="item"
        :theme="theme"
        :isHorizontal="isHorizontal"
      />
    </template>
  </Menu>
</template>
<script lang="ts">
import type { MenuState } from './types'
import {
  computed,
  defineComponent,
  unref,
  reactive,
  watch,
  toRefs,
  ref,
} from 'vue'
import { Menu } from 'ant-design-vue'
import BasicSubMenuItem from './components/BasicSubMenuItem.vue'
import { MenuModeEnum, MenuTypeEnum } from '@admin/tokens'
import { useOpenKeys } from './useOpenKeys'
import { RouteLocationNormalizedLoaded, useRouter } from 'vue-router'
import { isFunction } from '@admin/utils'
import { REDIRECT_NAME } from '@admin/tokens'
import { basicProps } from './props'
import { useMenuSetting } from '@/hooks/setting/useMenuSetting'
import { useDesign } from '@/hooks/web/useDesign'
import { getCurrentParentPath } from '@/router/menus'
import { listenerRouteChange } from '@/logics/mitt/routeChange'
import { getAllParentPath } from '@/router/helper/menuHelper'

export default defineComponent({
  name: 'BasicMenu',
  components: {
    Menu,
    BasicSubMenuItem,
  },
  props: basicProps,
  emits: ['menuClick'],
  setup(props, { emit }) {
    const isClickGo = ref(false)
    const currentActiveMenu = ref('')

    const menuState = reactive<MenuState>({
      defaultSelectedKeys: [],
      openKeys: [],
      selectedKeys: [],
      collapsedOpenKeys: [],
    })

    const { prefixCls } = useDesign('basic-menu')
    const { items, mode, accordion } = toRefs(props)

    const { getCollapsed, getTopMenuAlign, getSplit } = useMenuSetting()

    const { currentRoute } = useRouter()

    const { handleOpenChange, setOpenKeys, getOpenKeys } = useOpenKeys(
      menuState,
      items,
      mode as any,
      accordion,
    )

    const getIsTopMenu = computed(() => {
      const { type, mode } = props

      return (
        (type === MenuTypeEnum.TOP_MENU && mode === MenuModeEnum.HORIZONTAL) ||
        (props.isHorizontal && unref(getSplit))
      )
    })

    const getMenuClass = computed(() => {
      const align =
        props.isHorizontal && unref(getSplit) ? 'start' : unref(getTopMenuAlign)
      return [
        prefixCls,
        `justify-${align}`,
        {
          [`${prefixCls}__second`]: !props.isHorizontal && unref(getSplit),
          [`${prefixCls}__sidebar-hor`]: unref(getIsTopMenu),
        },
      ]
    })

    const getInlineCollapseOptions = computed(() => {
      const isInline = props.mode === MenuModeEnum.INLINE

      const inlineCollapseOptions: { inlineCollapsed?: boolean } = {}
      if (isInline) {
        inlineCollapseOptions.inlineCollapsed = props.mixSider
          ? false
          : unref(getCollapsed)
      }
      return inlineCollapseOptions
    })

    listenerRouteChange((route) => {
      if (route.name === REDIRECT_NAME) return
      handleMenuChange(route)
      currentActiveMenu.value = route.meta?.currentActiveMenu as string

      if (unref(currentActiveMenu)) {
        menuState.selectedKeys = [unref(currentActiveMenu)]
        setOpenKeys(unref(currentActiveMenu))
      }
    })

    !props.mixSider &&
      watch(
        () => props.items,
        () => {
          handleMenuChange()
        },
      )

    async function handleMenuClick({
      key,
    }: {
      key: string
      keyPath: string[]
    }) {
      const { beforeClickFn } = props
      if (beforeClickFn && isFunction(beforeClickFn)) {
        const flag = await beforeClickFn(key)
        if (!flag) return
      }
      emit('menuClick', key)

      isClickGo.value = true
      menuState.selectedKeys = [key]
    }

    async function handleMenuChange(route?: RouteLocationNormalizedLoaded) {
      if (unref(isClickGo)) {
        isClickGo.value = false
        return
      }
      const path =
        (route || unref(currentRoute)).meta?.currentActiveMenu ||
        (route || unref(currentRoute)).path
      setOpenKeys(path)
      if (unref(currentActiveMenu)) return
      if (props.isHorizontal && unref(getSplit)) {
        const parentPath = await getCurrentParentPath(path)
        menuState.selectedKeys = [parentPath]
      } else {
        const parentPaths = await getAllParentPath(props.items, path)
        menuState.selectedKeys = parentPaths
      }
    }

    return {
      handleMenuClick,
      getInlineCollapseOptions,
      getMenuClass,
      handleOpenChange,
      getOpenKeys,
      ...toRefs(menuState),
    }
  },
})
</script>
<style lang="less">
@import './index.less';
</style>
